#pragma once
#include "Function.hpp"

namespace zzz{

//f(x)=1/(sigma^2*2pi)*exp(-((x-meanx)^2+(y-meany)^2)/(2*sigma^2))
class Gaussian2DFunction : public Function<Vector2d,double>
{
public:
  Gaussian2DFunction()
    :Function<Vector2d,double>(Vector2d(MAX_DOUBLE,MAX_DOUBLE),
        Vector2d(-MAX_DOUBLE, -MAX_DOUBLE)),
        mean_(0),sigma_(0){}
  Gaussian2DFunction(Vector2d mean, double sigma)
    :Function<Vector2d,double>(Vector2d(MAX_DOUBLE,MAX_DOUBLE),
        Vector2d(-MAX_DOUBLE, -MAX_DOUBLE))
  {
    SetParameter(mean,sigma);
  }

  double Evaluate(const Vector2d& x)
  {
    return A_*exp(-(x-mean_).LenSqr()/(2*sigma_));
  }

  void SetParameter(Vector2d mean, double sigma)
  {
    mean_=mean;
    sigma_=sigma;
    s2_=sigma_*sigma_;
    A_=1.0/(sigma*sigma*2*PI);
  }
  bool CheckInput(const Vector2d& x)
  {
    return true;
  }

private:
  Vector2d mean_;
  double sigma_;

  double s2_;  //sigma^2
  double A_;    //amplifier
};
}
